<template>
  <u-popup :show="show" @close="close" mode="right" bgColor="transparent">
    <view class="cu-dept-user-select-wrap">
      <view class="content-wrap">
        <view class="header">
          <search v-if="selectMode === 'user'" ref="sea" @confirm="confirmSearch" />
          <view v-if="hasDeptData" class="title">
            <scroll-view scroll-x style="width: 100%; white-space: nowrap" :scroll-left="scrollLeft">
              <view class="uni-inline-item">
                <view v-for="(item, index) in tree_stack" class="uni-inline-item" :key="index">
                  <view class="uni-inline-item" v-if="index == 0" @click="backTree(item, -1)">
                    <text :class="[isActive(index) && !showSearchResult ? 'none' : 'active']">通讯录</text>
                  </view>
                  <view class="uni-inline-item" v-if="index == 0 && showSearchResult" @click="backTree(item, -2)">
                    <u-icon name="arrow-right" size="12" color="#999999"></u-icon>
                    <text
                      :class="[
                        index == tree_stack.length - 1 && showSearchResult ? 'none' : 'active',
                        'uni-inline-item'
                      ]"
                      >搜索结果</text
                    >
                  </view>
                  <view class="uni-inline-item" @click="backTree(item, index)" v-if="index != 0">
                    <u-icon name="arrow-right" size="12" color="#999999"></u-icon>
                    <view :class="isActive(index) ? 'none inline-ite' : 'active'"> {{ item[deptLabel] }} </view>
                  </view>
                </view>
              </view>
            </scroll-view>
          </view>
          <u-gap bgColor="#F5F5F5" height="8" v-if="multiple"></u-gap>
        </view>
        <view style="flex: 1">
          <view class="select-all-wrap" @click="selectAllHandle" v-if="multiple">
            <SelectStatus :checked="selectAllStatus" />
            <view>全选</view>
          </view>
          <u-gap bgColor="#F5F5F5" height="8"></u-gap>
          <scroll-view
            scroll-y="true"
            class="user-scroll-wrap"
            :style="{ height: safeArea.height - 40 - 54 - 60 - (multiple ? 58 : 0) + 'px' }"
            @scrolltolower="handleScrolltolower"
          >
            <view class="container-list">
              <view
                class="common"
                v-for="(item, index) in deptListData"
                @click="handleDeptClick(item, index)"
                :key="item[deptValue]"
              >
                <label class="info-content">
                  <view class="uni-inline-item">
                    <view v-if="selectMode === 'dept'" class="select-icon-wrap" @click.stop="handleDeptClick(item, -1)">
                      <SelectStatus :checked="isDeptSelect(item)" />
                    </view>
                    <view class="dept-icon-wrap">
                      <image class="dept-icon" src="./image/default_dept_icon.png" mode="aspectFit"> </image>
                    </view>
                    <view class="dept-name"> {{ item[deptLabel] }}</view>
                  </view>
                  <view class="uni-inline-item">
                    <view class="user-num" v-if="selectMode === 'user' && withCount">{{ item.staffCount }}</view>
                    <u-icon name="arrow-right" v-if="item.children" size="12" color="#999999"></u-icon>
                  </view>
                </label>
              </view>
              <template v-if="selectMode === 'user'">
                <view
                  class="common"
                  v-for="(item, index) in userListData"
                  @click="handleUserClick(item, index)"
                  :key="item.userId"
                >
                  <label class="info-content">
                    <view class="uni-inline-item">
                      <view class="select-icon-wrap">
                        <SelectStatus :checked="isUserSelect(item)" />
                      </view>
                      <view class="user-icon-wrap">
                        <image v-if="item.avatar" class="user-icon" :src="staticUrl + item.avatar" mode="aspectFit">
                        </image>
                        <image v-else class="user-icon" src="/static/images/default_avatar_icon.png" mode="aspectFit">
                        </image>
                      </view>
                      <view class="dept-name u-line-1"> {{ item.name }}</view>
                    </view>
                    <view class="uni-inline-item" v-if="item.children">
                      <view class="user-num" v-if="selectMode === 'user'">{{ item.staffCount }} </view>
                      <u-icon name="arrow-right" size="12" color="#999999"></u-icon>
                    </view>
                  </label>
                </view>
              </template>

              <template v-if="deptListData.length === 0 && userListData.length === 0">
                <u-empty mode="data" marginTop="100"></u-empty>
              </template>
            </view>
          </scroll-view>
        </view>
        <view class="btn box_sizing">
          <!-- 多选底部信息 -->
          <!-- <view class="bottom-btn-wrap" v-if="multiple" @click="selectedInfoPopup = true">
						<template v-if="userCheckList.length > 0 || deptCheckList.length > 0">
							<view class="selected-text u-line-1" v-if="selectMode === 'user'">
								已选择：{{ getUserNum }}人,其中有{{ deptCheckList.length }}个部门（含子部门)
							</view>
							<view class="selected-text u-line-1" v-else>
								已选择：{{ deptCheckList.length }}个部门
							</view>
						</template>
						<view class="selected-text" v-else>未选择</view>
						<u-icon class="arrow-up" name="arrow-up" size="12" color="#2c7be7"></u-icon>
						<button class="confirm-btn" type="primary" @click.stop="backConfirm">
							<text v-if="selectMode === 'user'">确定({{ getUserNum || 0 }}/999)</text>
							<text v-else>确定({{ deptCheckList.length || 0 }}/999)</text>
						</button>
					</view> -->
          <view class="bottom-btn-wrap" v-if="multiple" @click="selectedInfoPopup = true">
            <template v-if="userCheckList.length > 0 || deptCheckList.length > 0">
              <view class="selected-text u-line-1" v-if="selectMode === 'user'"> 已选择：{{ getUserNum }}人 </view>
              <view class="selected-text u-line-1" v-else> 已选择：{{ deptCheckList.length }}个部门 </view>
            </template>
            <view class="selected-text" v-else>未选择</view>
            <u-icon class="arrow-up" name="arrow-up" size="12" color="#2c7be7"></u-icon>
            <button class="confirm-btn" type="primary" @click.stop="backConfirm">
              <text>确定</text>
            </button>
          </view>

          <!-- 单选底部信息 -->
          <view class="bottom-btn-wrap" v-else>
            <template v-if="userCheckList.length > 0 || deptCheckList.length > 0">
              <view class="selected-text u-line-1" v-if="selectMode === 'user'">
                已选择：{{ userCheckList[0].name }}
              </view>
              <view class="selected-text u-line-1" v-else> 已选择：{{ deptCheckList[0][deptLabel] }} </view>
            </template>
            <view class="selected-text" v-else>未选择</view>
            <button class="confirm-btn" type="primary" @click.stop="backConfirm">确定</button>
          </view>
        </view>
      </view>
      <u-popup :show="selectedInfoPopup" mode="bottom" @close="selectedInfoPopup = false" round="10">
        <view class="selected-inof-popup-wrap">
          <view class="uni-inline-item popup-header">
            <view class="selected-text u-line-1" v-if="selectMode === 'user'"> 已选择：{{ getUserNum }}人 </view>
            <view class="selected-text u-line-1" v-else> 已选择：{{ deptCheckList.length }}个部门 </view>
            <view class="close-popup-btn" @click="selectedInfoPopup = false">关闭</view>
          </view>
          <scroll-view scroll-y="true" class="user-scroll-wrap">
            <template>
              <view
                class="common"
                v-for="item in deptCheckList"
                @click="handleDeptClick(item, -1)"
                :key="item[deptValue]"
              >
                <label class="info-content">
                  <view class="uni-inline-item">
                    <!-- 多选 -->
                    <view class="select-icon-wrap">
                      <SelectStatus :checked="isDeptSelect(item)" />
                    </view>
                    <view class="dept-icon-wrap">
                      <image class="dept-icon" src="./image/default_dept_icon.png" mode="aspectFit"> </image>
                    </view>
                    <view class="dept-name u-line-1"> {{ item[deptLabel] }}</view>
                  </view>
                  <view class="uni-inline-item" v-if="item.children"> </view>
                </label>
              </view>
            </template>
            <u-gap bgColor="#F5F5F5" height="8"></u-gap>
            <template v-if="selectMode === 'user'">
              <view
                class="common"
                v-for="(item, index) in userCheckList"
                @click="handleUserClick(item, index)"
                :key="item.userId"
              >
                <label class="info-content">
                  <view class="uni-inline-item">
                    <view class="select-icon-wrap">
                      <SelectStatus :checked="isUserSelect(item)" />
                    </view>
                    <view class="user-icon-wrap">
                      <image v-if="item.avatar" class="user-icon" :src="staticUrl + item.avatar" mode="aspectFit">
                      </image>
                      <image v-else class="user-icon" src="/static/image/default_avatar_icon.png" mode="aspectFit">
                      </image>
                    </view>
                    <view class="dept-name u-line-1"> {{ item.name }}</view>
                  </view>
                  <view class="uni-inline-item" v-if="item.children">
                    <!-- <view class="user-num" v-if="selectMode === 'user'">{{ item.staffCount }}</view> -->
                    <u-icon name="arrow-right" size="12" color="#999999"></u-icon>
                  </view>
                </label>
              </view>
            </template>
          </scroll-view>
        </view>
      </u-popup>
    </view>
  </u-popup>
</template>

<script>
import { staticUrl } from '@/config.js'
import { reqDeptData } from '@/api/system/dept'
import { listUserPagingV2 } from '@/api/system/user'
import Search from './components/Search.vue'
import SelectStatus from './components/SelectStatus.vue'

export default {
  data() {
    return {
      hasDeptData: false,
      keyword: '',
      staticUrl: staticUrl,
      showSearchResult: false, // 是否搜索1
      deptListData: [], // 部门数据
      userListData: [], // 部门下用户数据
      catchTreeNone: [],
      tree_stack: ['通讯录'],
      searchResult: [],
      deptCheckList: [],
      scrollLeft: 999,
      nodePathArray: [],
      userCheckList: [], // 已选中用户数据
      selectedInfoPopup: false, // 已选择人员信息
      show: false,
      safeArea: { height: 0 },
      pageNum: 1,
      pageSize: 20,
      total: 0,
      currentDeptId: ''
    }
  },
  components: {
    Search,
    SelectStatus
  },
  computed: {
    allDeptUserCount() {
      let sum = 0
      this.deptListData.map((item) => {
        sum += item.staffCount
        return item
      })
      return sum
    },
    selectAllStatus() {
      if (this.selectMode === 'user') {
        let total = 0
        for (const user of this.userListData) {
          if (this.userCheckList.find((j) => j.userId === user.userId)) {
            total++
          }
        }
        return this.userListData.length === total && total > 0
      } else {
        if (this.deptListData.length === 0) return false
        return this.deptListData.every((i) => {
          return this.deptCheckList.some((j) => j[this.deptValue] === i[this.deptValue])
        })
      }
    },
    // 选中的人数
    getUserNum() {
      let sum = 0
      sum += this.userCheckList.length
      this.deptCheckList.forEach((item) => {
        sum += item.staffCount
      })
      return sum
    },
    // 用户是否选中
    isUserSelect() {
      const userCheckList = this.userCheckList
      return (item) => {
        if (userCheckList.length === 0) {
          return false
        }
        const i = userCheckList.some((e) => item.userId === e.userId)
        return i
      }
    },
    // 部门是否选中
    isDeptSelect() {
      return (item) => {
        const index =
          this.deptCheckList.findIndex((e) => {
            return item[this.deptValue] === e[this.deptValue]
          }) > -1
        return index
      }
    },
    isActive() {
      return (index) => {
        return index === this.tree_stack.length - 1
      }
    }
  },
  mounted() {
    uni.getSystemInfo({
      success: (res) => {
        this.safeArea = res.safeArea
      },
      fail: (err) => {
        reject(err)
      }
    })
  },
  methods: {
    // 滚动到底部加载下一页数据
    handleScrolltolower() {
      if (this.pageSize * this.pageNum >= this.total) {
        return
      }
      this.pageNum += 1
      this.getDeptUser(this.currentDeptId)
    },

    getSystemInfo() {
      return new Promise((resolve, reject) => {
        uni.getSystemInfo({
          success: (res) => {
            resolve(res)
          },
          fail: (err) => {
            reject(err)
          }
        })
      })
    },
    reset() {
      this.userCheckList = []
      this.deptCheckList = []
      this.backTree('通讯录', -1)
      uni.hideLoading()
    },
    open() {
      this.keyword = ''
      this.$nextTick(() => {
        if (this.selectMode === 'user') {
          if (!Array.isArray(this.checkList)) {
            this.userCheckList = []
          } else {
            this.userCheckList = JSON.parse(JSON.stringify(this.checkList))
          }
        } else {
          if (!Array.isArray(this.checkList)) {
            this.deptCheckList = []
          } else {
            this.deptCheckList = JSON.parse(JSON.stringify(this.checkList))
          }
        }
        this.Init()
        this.show = true
      })
    },
    close() {
      this.show = false
      this.$emit('close')
      this.reset()
    },
    selectAllHandle() {
      if (this.selectAllStatus) {
        // 反选
        this.userCheckList = this.deleteArr(this.userListData, this.userCheckList, 'userId')
        this.deptCheckList = this.deleteArr(this.deptCheckList, this.deptListData, this.deptValue)
      } else {
        // 全选
        this.userCheckList = this.combineArr(this.userListData, this.userCheckList, 'userId')
        if (this.selectMode === 'dept') {
          this.deptCheckList = this.combineArr(this.deptListData, this.deptCheckList, this.deptValue)
        }
      }
    },
    // 数组合并去重 （全选）
    combineArr(arr1, arr2, key) {
      const arrs = [...arr1, ...arr2]
      // 根据key去重
      const map = new Map()
      for (const item of arrs) {
        // // 选择人员时, 部门下面人员为0 不可选中
        // if (this.selectMode === 'user' && item.staffCount <= 0) {
        // 	break
        // }
        if (!map.has(item[key])) {
          map.set(item[key], item)
        }
      }
      return [...map.values()]
    },
    // 数组合并删除 (反选)
    deleteArr(arr1, arr2, key) {
      const arrs = [...arr1, ...arr2]
      // 根据key去重
      const map = new Map()
      for (const item of arrs) {
        if (map.has(item[key])) {
          map.delete(item[key])
        } else {
          map.set(item[key], item)
        }
      }
      return [...map.values()]
    },
    // 初始化
    async Init() {
      this.getDept()
    },
    async getDept() {
      let res = []
      if (this.deptRequestApi) {
        res = await this.deptRequestApi()
      } else {
        res = await reqDeptData({
          containUnAssign: false, // 不包含管理员
          containChildren: true, // 包含子部门人员数量
          pageSize: 9999,
          withCount: this.withCount,
          ...this.expandFields
        })
      }

      res.data = res.data || res.rows
      this.hasDeptData = res.data.length > 0

      // 如果有deptId，则需要过滤部门树
      this.deptListData = res.data
      if (this.deptId) {
        this.deptListData = this.filterDeptTree(res.data, this.deptId)
      }
      if (this.selectMode === 'user' && this.autoRequestUser) {
        this.handleDeptClick(this.deptListData[0] ?? '', 0)
      }
      this.catchTreeNone = this.deptListData
    },
    filterDeptTree(originData, deptId) {
      let result = []
      function recursiveFilter(items) {
        items.forEach((item) => {
          if (item.id === deptId) {
            result.push(item)
          } else if (item.children) {
            recursiveFilter(item.children)
          }
        })
      }

      recursiveFilter(originData)

      return result
    },
    // 部门点击处理
    async handleDeptClick(item, index) {
      if (index > -1) {
        if (this.selectMode === 'user') {
          this.pageNum = 1
          await this.getDeptUser(item[this.deptValue])
          this.toChildren(item)
        } else {
          const children = this.treeProp.children

          if (item[children]) {
            this.toChildren(item)
          } else {
            this.deptRadioClick(item, index)
          }
        }
      } else if (this.multiple) {
        this.deptMultipleClick(item, index)
      } else {
        this.deptRadioClick(item, index)
      }
    },
    // 部门单选
    deptRadioClick(item, index) {
      if ((!this.multiple && this.selectMode === 'user') || this.selectMode === 'user') {
        return
      }
      this.$set(this, 'deptCheckList', [
        {
          ...item
        }
      ])
    },
    // 部门多选
    deptMultipleClick(item, index) {
      if (this.selectMode === 'user') return
      const findIdex = this.deptCheckList.findIndex((e) => item[this.deptValue] === e[this.deptValue])
      if (findIdex > -1) {
        this.deptCheckList.splice(findIdex, 1)
      } else {
        this.deptCheckList.push(item)
      }
    },
    // 人员点击处理
    handleUserClick(item, index) {
      if (this.multiple) {
        this.userMultipleClick(item, index)
      } else {
        this.userRadioClick(item, index)
      }
    },
    // 人员单选
    userRadioClick(item, index) {
      const path = this.getPath()
      this.$set(this, 'userCheckList', [
        {
          ...item,
          path
        }
      ])
    },
    // 人员多选
    userMultipleClick(item, index) {
      if (!this.multiple) return
      const findIdex = this.userCheckList.findIndex((e) => item.userId === e.userId)
      if (findIdex > -1) {
        this.userCheckList.splice(findIdex, 1)
      } else {
        this.userCheckList.push(item)
      }
    },
    // 获取部门用户
    async getDeptUser(deptId) {
      return new Promise(async (resolve, reject) => {
        uni.showLoading({
          title: '加载中'
        })
        this.currentDeptId = deptId
        let res = []
        const params = {
          deptId,
          pageNum: this.pageNum,
          pageSize: this.pageSize,
          keyword: this.keyword,
          ...this.expandFields
        }
        if (this.userRequestApi) {
          res = await this.userRequestApi(params)
        } else {
          res = await listUserPagingV2(params)
        }
        const arr = []
        res.rows = res.rows || res.data
        this.total = res.total || 0
        for (let i = 0; i < res.rows.length; i++) {
          // 排除部分 用户id
          if (this.excludeIds.indexOf(res.rows[i].userId) === -1) {
            arr.push(res.rows[i])
          }
        }
        if (this.pageNum === 1) {
          this.userListData.splice(0, this.userListData.length, ...arr)
        } else {
          this.userListData.push(...arr)
        }
        uni.hideLoading()
        resolve()
      })
    },
    // 获取路径
    getPath() {
      const path = [...this.tree_stack].map((e) => {
        const item = Object.assign({}, e)
        delete item[this.treeProp.children]
        return item
      })
      return path.slice(1, path.length) || []
    },
    // 到下一级
    toChildren(item) {
      if (item.user) return

      const children = this.treeProp.children
      this.deptListData = item[children] || []
      uni.showLoading({
        title: '加载中'
      })
      this.tree_stack.push(item)
      this.$nextTick(() => {
        uni.hideLoading()
        this.scrollLeft += 200
      })
    },
    // 搜索
    async confirmSearch(val) {
      this.keyword = val.trim()
      this.pageNum = 1
      const deptId = this.deptId || ''
      this.currentDeptId = deptId
      await this.getDeptUser(deptId)
      this.deptListData = []
      this.showSearchResult = true
      this.tree_stack.splice(1, 1000)
    },

    // 返回其它层
    async backTree(item, index) {
      const that = this
      const treeStack = that.tree_stack
      const max = 300
      this.pageNum = 1
      if (index === -1) {
        this.keyword = ''
        this.currentDeptId = ''
        // 返回通讯录顶层
        that.deptListData = that.catchTreeNone
        that.tree_stack.splice(1, max)
        that.showSearchResult = false
        if (this.selectMode === 'user') that.$refs.sea.clears()
        this.userListData = []
      } else if (index === -2) {
        this.keyword = ''
        this.currentDeptId = ''
        // 搜索
        that.deptListData = that.searchResult
        that.tree_stack.splice(1, max)
      } else {
        if (treeStack.length - index > 2) {
          that.tree_stack.splice(index + 1, max)
        } else if (index !== treeStack.length - 1) {
          that.tree_stack.splice(treeStack.length - 1, 1)
        }
        if (this.selectMode === 'user') {
          await this.getDeptUser(this.tree_stack[this.tree_stack.length - 1][this.deptValue])
        }

        that.deptListData = item[that.treeProp.children]
      }
      this.$forceUpdate()
    },
    async backConfirm() {
      if (this.deptCheckList.length > 0 && this.selectMode === 'user') {
        let arr = []
        for (let i = 0; i < this.deptCheckList.length; i++) {
          const data = {
            deptId: this.deptCheckList[i][this.deptValue],
            containChildren: true
          }
          let res = {}
          if (this.userRequestApi) {
            res = await this.userRequestApi(data)
          } else {
            res = await listUserPagingV2(data)
          }
          arr = this.combineArr(res.rows, arr, 'userId')
        }
        arr = this.combineArr(arr, this.userCheckList, 'userId')
        this.$emit('change', JSON.parse(JSON.stringify(arr)))
      } else {
        if (this.selectMode === 'user') {
          this.$emit('change', this.userCheckList)
        } else {
          const deptList = []
          this.deptCheckList.forEach((item) => {
            deptList.push({
              ...item,
              deptId: item[this.deptValue],
              deptName: item[this.deptLabel]
            })
          })
          this.$emit('change', JSON.parse(JSON.stringify(deptList)))
        }
      }
      this.close()
    }
  },
  props: {
    checkList: {
      type: [Number, String, Array]
    },
    // 排除的用户ID
    excludeIds: {
      type: Array,
      default: () => {
        return []
      }
    },
    treeProp: {
      type: Object,
      default: () => {
        return {
          label: 'name',
          children: 'children',
          checkStrictly: false // 不关联
        }
      }
    },
    multiple: {
      type: Boolean,
      default: false
    },
    deptId: {
      type: [String, Number],
      default: ''
    },
    selectMode: {
      type: String,
      default: 'user'
    },
    deptLabel: {
      type: String,
      default: 'label'
    },
    deptValue: {
      type: String,
      default: 'id'
    },
    deptRequestApi: {
      type: Function
    },
    userRequestApi: {
      type: Function
    },
    expandFields: {
      type: Object,
      default: () => {}
    },
    // 初始化时，自动加载用户数据
    autoRequestUser: {
      type: Boolean,
      default: false
    },
    withCount: {
      type: Boolean,
      default: true
    }
  }
}
</script>
<style lang="scss" scoped>
@import './css/style.scss';
</style>
